﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Vortex.Drawing {

	/// <summary>
	/// Caches shader constant data
	/// </summary>
	class ConstantCache {
		private uint _registerSize;
		private byte[] _data = new byte[0];

		/// <summary>
		/// Initializes a new instance of the <see cref="ConstantCache"/> class.
		/// </summary>
		/// <param name="registerSize">Size of the register.</param>
		public ConstantCache(uint registerSize) {
			_registerSize = registerSize;
		}

		/// <summary>
		/// Sets the constant value.
		/// </summary>
		/// <param name="startRegister">The start register index.</param>
		/// <param name="pValue">The pointer to value data.</param>
		/// <param name="registerCount">The register count.</param>
		public unsafe void SetValue(uint startRegister, void* pValue, uint registerCount) {
			EnsureSize((startRegister + registerCount) * _registerSize);

			unsafe {
				byte* pSource = (byte*)pValue;
				uint startByte = startRegister * _registerSize;
				uint byteCount = registerCount * _registerSize;

				for (uint n = 0; n < byteCount; ++n) {
					_data[startByte + n] = pSource[n];
				}
			}
		}

		/// <summary>
		/// Ensures the buffer size.
		/// </summary>
		/// <param name="size">The size.</param>
		private void EnsureSize(uint size) {
			if ((uint)_data.Length < size) {
				byte[] newData = new byte[size];
				if (_data.Length > 0) {
					Array.Copy(_data, newData, _data.Length);
				}
				_data = newData;
			}
		}

		/// <summary>
		/// Number of cached registers.
		/// </summary>
		/// <value>The register count.</value>
		public uint RegisterCount {
			get { return (uint)_data.Length / _registerSize; }
		}

		/// <summary>
		/// Gets the constant fata.
		/// </summary>
		/// <value>The values of cached constants.</value>
		public byte[] Data {
			get { return _data; }
		}

		/// <summary>
		/// Gets a value indicating whether this cache is empty.
		/// </summary>
		/// <value><c>true</c> if this instance is empty; otherwise, <c>false</c>.</value>
		public bool IsEmpty {
			get { return _data.Length == 0; }
		}
	}
}
